/* * Simple function to request a guaranteed rate reservation. * Input: * fd file descriptor to be guaranteed * dur duration of guarantee in seconds * bps bytes per second required * flag one of SOFT_ or HARD_GUARANTEE [+VOD_LAYOUT] * (extra entry points included for those who do not * want to include sys/grio.h) * * Assumed: * reservation start time of "1 second from now" * guarantee unit time of 1 second * * Returns: * 0 success, guarantee granted * -1 error returned and displayed with perror() * +n n is the best bytes/second that XFS can offer * * Usage: * #define BEST_RATE zillions * #define MINIMAL_RATE somewhat_less * if ( (ret = requestRate(fd, dur, BEST_RATE, SOFT_GUARANTEE)) ) * { // not a success * if (ret >= MINIMAL_RATE) // acceptable lower rate offered * ret = requestRate(fd, dur, ret, SOFT_GUARANTEE); * } * if (ret) // failed for some reason * { * if (0<ret) // not an error as such * fprintf(stderr, "Cannot get rate\n"); * exit(); * } * // guaranteed rate obtained, continue */ #include <sys/types.h> /* for time_t */ #include <time.h> /* for time() */ #include <errno.h> /* for error codes */ #include <stdio.h> /* [fs]printf() */ #include "grio.h" /* for grio_* */ /* * This subroutine displays a diagnostic message to stderr when * grio_request() returns an error. perror() cannot be used in * this case because the generic messages are not descriptive. * */ void printGRIOerror( grio_resv_t *g ) { char work[80]; char *msg = work; switch (g->gr_error) { case EINVAL: { msg = "unable to contact grio daemon"; break; } case EBADF: { msg = "cannot stat file, or file already guaranteed"; break; } case ESRCH: { msg = "invalid procid"; break; } case ENOENT: { msg = "file has no (real-time?) extents"; break; } case EIO: { msg = "incorrect start time"; break; } case EACCES: { msg = (g->gr_flags & VOD_LAYOUT) ? "unable to provide VOD guarantee" : ( (g->gr_flags & HARD_GUARANTEE) ? "unable to provide HARD guarantee" : "unable to provide SOFT guarantee" ); break; } case ENOSPC: { sprintf(work, "out of bandwidth on device %s", g->gr_errordev); break; } default: /* in case they think of something else */ { sprintf(work, "error %d", g->gr_error); } } fprintf(stderr, "grio_request: %s.\n", msg); } /* * This function actually places the request. */ int requestRate( int fd, int dur, int bps, int flag) { int ret; grio_resv_t grio; grio.gr_duration= dur; grio.gr_start = 1+time(NULL); grio.gr_optime = 1; /* unit time is 1 second */ grio.gr_opsize = bps; grio.gr_flags = flag; ret = grio_request(fd, &grio); if (ret) /* not a success */ { if ( (ENOSPC == grio.gr_error) /* insufficient bandwidth.. */ && (grio.gr_opsize) ) /* ..but nonzero rate remaining */ ret = grio.gr_opsize; /* return available rate */ else /* some other problem or 0 bandwidth available */ printGRIOerror(&grio); } return ret; } /* * When you don't want to #include sys/grio.h to define one constant... */ int requestHardRate( int fd, int dur, int bps ) { return requestRate(fd, dur, bps, HARD_GUARANTEE); } int requestSoftRate( int fd, int dur, int bps ) { return requestRate(fd, dur, bps, SOFT_GUARANTEE); } #ifdef UNIT_TEST #include <sys/stat.h> #include <fcntl.h> /* requestRate pathname [rate [duration [flags ] ] ] */ int main(int argc, char **argv) { int fd = open(argv[1], O_RDONLY); int bps = 1000000; /* 1MB */ int dur = 60; /* a new york minute */ int flg = SOFT_GUARANTEE; int rc; if (argc > 2) bps = atoi(argv[2]); if (argc > 3) dur = atoi(argv[3]); if (argc > 4) flg = atoi(argv[4]); printf("Requesting guarantee on fd=%d of %d bps for %d sec\n", fd, bps, dur); rc = requestRate(fd, dur, bps, flg); printf("requestRate() returns %d\n", rc); } #endif /*UNIT_TEST*/